package com.yuyou.fn.educational.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.service.ISiteConfigService;
import com.yuyou.fn.common.util.BigDecimals;
import com.yuyou.fn.common.util.OkHttpClientUtils;
import com.yuyou.fn.common.util.Principals;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.educational.service.IEmployeeDiscountService;
import com.yuyou.fn.educational.vo.EmployeeDiscountVo;
import okhttp3.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;

@Service
public class EmployeeDiscountServiceImpl implements IEmployeeDiscountService{

    private final Logger log = LoggerFactory.getLogger(EmployeeDiscountServiceImpl.class);

    private OkHttpClient okHttpClient = OkHttpClientUtils.getIgnoreSsLClient(6,10 );

    private String serviceBaseUrl = null ;

    private String appkey = null ;

    @Value("${dev.env}")
    private boolean dev;

    @Resource
    private RedisTemplate<String,String> redisTemplate;


    @Resource
    private ISiteConfigService siteConfigService;

    @PostConstruct
    public void init(){
        serviceBaseUrl = siteConfigService.getConfigValueFromCache("zy_nbyh_base_url");
        appkey = siteConfigService.getConfigValueFromCache("zy_nbyh_appkey");
        if(dev && !serviceBaseUrl.contains("test")){
            throw new IllegalStateException("Invalid config");
        }
    }

    @Override
    public EmployeeDiscountVo checkCode(Long courseOrderId,String discountCode, String studentName,String studentNo) {

        if(isLock( courseOrderId, discountCode) ){
            throw new BusException("此优惠码暂时锁定，请稍后再试");
        }

        return query(discountCode, studentName, studentNo);
    }

    public EmployeeDiscountVo query(String discountCode, String studentName, String studentNo) {
        RequestBody body = new FormBody.Builder()
                .add("systemType", "4")
                .add("couponCode", discountCode)
                .add("studentName", studentName)
                .add("studentCode", studentNo)
                .add("encryKey", calEncryKey("4",appkey,discountCode,studentNo))
                .build();


        Request request = new Request.Builder().url(serviceBaseUrl + "/api/queryCode").post(body).build();
        Call call = okHttpClient.newCall(request);

        JSONObject ret  = null ;

        Response response = null ;
        try {
            response = call.execute();
            String retStr = response.body().string();
            log.info("[优惠查询返回结果]" + retStr);
            ret = JSONObject.parseObject(retStr);
        } catch (IOException e) {
            throw new BusException("卓越内部员工系统服务出错");
        }finally {
            if(response != null ){
                response.close();
            }
        }

        if( ret.getIntValue("code") != 200 ){
            throw new BusException(ret.getString("msg"));
        }

        EmployeeDiscountVo employeeDiscountVo = ret.getJSONObject("data").toJavaObject(EmployeeDiscountVo.class);
        valid(employeeDiscountVo);
        return employeeDiscountVo;
    }


    @Override
    public void updateUsedStatus(Long courseOrderId, BigDecimal orderTotalAmount, String discountCode, BigDecimal discountAmount, String studentName, String studentNo,String version , Principals.Principal principal) {

        unlock(discountCode);

        if(version == null ){
            version = "1";
        }


        RequestBody body = new FormBody.Builder()
                .add("systemType", "4")
                .add("couponCode", discountCode)
                .add("studentName", studentName)
                .add("studentCode", studentNo)
                .add("createUserName", principal.name)
                .add("createUserId", String.valueOf(principal.id))
                .add("version", version)
                .add("fromSystem", "誉优")
                .add("discountMoney", BigDecimals.formatBigDecimal(discountAmount,"0.00"))
                .add("orderNumber", String.valueOf(courseOrderId))
                .add("orderMoney", BigDecimals.formatBigDecimal(orderTotalAmount,"0.00"))
                .add("encryKey", calEncryKey("4",studentNo,appkey,version))
                .build();


        Request request = new Request.Builder().url(serviceBaseUrl + "/api/notifyCodeUsed").post(body).build();
        Call call = okHttpClient.newCall(request);

        JSONObject ret  = null ;

        Response response = null  ;
        try {
            response = call.execute();
            String retStr =response.body().string();
            log.info("[优惠更新返回结果]" + retStr);
            ret = JSONObject.parseObject(retStr);
        } catch (IOException e) {
            throw new BusException("卓越内部员工系统服务出错");
        }finally {
            if(response != null ){
                response.close();
            }
        }

        if( ret.getIntValue("code") != 200 ){
            throw new BusException(ret.getString("msg"));
        }



    }

    private void valid(EmployeeDiscountVo employeeDiscountVo) {
        if(employeeDiscountVo.getAvailableUseNum() == 0 ){
            throw new BusException("优惠码不可用");
        }
        if(employeeDiscountVo.getBeginDate().after(TimeUtils.now()) || DateUtils.addDays(employeeDiscountVo.getEndDate(),1).before(TimeUtils.now())){
            throw new BusException("优惠码已经过期");
        }
    }


    private String calEncryKey(Object ... params) {
        return DigestUtils.md5Hex(StringUtils.join(params,"")).toLowerCase();
    }

    private boolean isLock(Long courseOrderId,String discountCode) {
        String lockCourseOrderId = (String)redisTemplate.opsForHash().get("zy_nbyh_lock", discountCode);
        if(lockCourseOrderId != null && !lockCourseOrderId.equals(String.valueOf(courseOrderId))){
            return true ;
        }
        return false ;

    }

    @Override
    public void lock(Long courseOrderId,String discountCode) {
        redisTemplate.opsForHash().put("zy_nbyh_lock", discountCode,String.valueOf(courseOrderId));
    }

    @Override
    public void unlock(String discountCode) {
        redisTemplate.opsForHash().delete("zy_nbyh_lock",discountCode);
    }
}
